import json
import click
from requests import get, post, exceptions
from urllib.parse import urljoin  # 新增：导入URL解析工具
def alve_test():
    try:
        r = get(url="https://ql2hew.i996.me/alive-test.html", headers={'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'})
    except:
        click.secho("无法连接到测试服务器", fg="red")
        return -1
    if r.text == '<meta name="alive-test" content="success">\n':
        click.secho("网络连通性正常", fg="green")
        return 0
    else:
        click.secho("无法连接到测试服务器:" + r.text, fg="red")
    return -1
@click.command()
@click.option('-u', '--url', help='目标URL地址')
@click.option('-m', '--method', default='GET', type=click.Choice(['GET', 'POST']), help='HTTP请求方法 (GET/POST)')
@click.option('-U', '--user-agent', is_flag=True, help='使用模拟浏览器的User-Agent')
@click.option('-d', '--data', help='POST请求的数据 (JSON格式)')
@click.option('-i', '--insecure', is_flag=True, help='跳过SSL证书验证')
@click.option('-t', '--timeout', default=10, help='请求超时时间(秒)，默认10秒')
@click.option('-r', '--redirect', default=5, help='最多跟踪重定向数量，默认5次')
@click.option('-a', '--alive-test', is_flag=True, help="网络测试")

def http_request_tool(url, method, user_agent, data, insecure, timeout, redirect, alive_test):
    """
    简易HTTP请求工具，支持GET/POST方法，模拟curl功能。
    """
    # 设置请求头
    headers = {}
    if user_agent:
        headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    
    # 处理POST数据
    post_data = None
    if method == 'POST' and data:
        try:
            post_data = json.loads(data)
        except json.JSONDecodeError:
            click.secho(f'错误: 无效的JSON数据 - {data}', fg='red')
            return
    if alive_test:
        alve_test()
        return
    else:
        if alve_test() != 0:
            click.secho("未连通网络，强制退出", fg="yellow")
            return
    if not url:
        return
    # 发送请求
    try:
        response = send_request(
            url=url,
            method=method,
            headers=headers,
            data=post_data,
            verify=not insecure,
            timeout=timeout,
            max_redirects=redirect
        )
        
        # 显示响应状态码
        if response.status_code >= 400:
            click.secho(f'状态码: {response.status_code}', fg='red')
        else:
            click.secho(f'状态码: {response.status_code}', fg='green')
            
        # 显示响应内容
        click.secho('响应内容:', fg='white')
        click.secho(response.text, fg='white')
        
    except exceptions.RequestException as e:
        click.secho(f'请求错误: {str(e)}', fg='red')
    except Exception as e:
        click.secho(f'发生错误: {str(e)}', fg='red')

def send_request(url, method='GET', headers=None, data=None, verify=True, timeout=10, max_redirects=5, redirect_count=0):
    """发送HTTP请求并处理重定向，支持相对路径Location头解析"""
    if redirect_count > max_redirects:
        raise exceptions.TooManyRedirects(f'超过最大重定向次数: {max_redirects}')
    
    headers = headers or {}
    try:
        if method.upper() == 'POST':
            response = post(url, headers=headers, json=data, verify=verify, timeout=timeout, allow_redirects=False)
        else:
            response = get(url, headers=headers, verify=verify, timeout=timeout, allow_redirects=False)
            
        # 处理重定向 (301, 302, 307, 308)
        if response.status_code in (301, 302, 307, 308):
            redirect_url = response.headers.get('Location')
            if not redirect_url:
                return response
                
            # 关键修复：使用urljoin解析相对路径URL
            # 将相对路径（如"/get"）与原URL（如"http://httpbin.org/redirect/1"）合并
            absolute_redirect_url = urljoin(url, redirect_url)
            click.secho(f'重定向 ({response.status_code}): {absolute_redirect_url}', fg='yellow')
            
            return send_request(
                url=absolute_redirect_url,  # 使用解析后的绝对URL
                method=method,
                headers=headers,
                data=data,
                verify=verify,
                timeout=timeout,
                max_redirects=max_redirects,
                redirect_count=redirect_count + 1
            )
            
        return response
        
    except exceptions.RequestException as e:
        raise

if __name__ == '__main__':
    http_request_tool()